/*
 * SoundMachine.h
 *
 *  Created on: 2011-2-25
 *      Author: hao
 */

#ifndef SOUNDMACHINE_H_
#define SOUNDMACHINE_H_

#include <iostream>
#include <functional>
#include <pulse/pulseaudio.h>
#include <semaphore.h>
#include "Error.h"

namespace StreamState {

    enum {
        STREAM_PLAYING,
        STREAM_STOP,
        STREAM_PAUSE,

    };

}

class SoundMachine {
    
    static bool bEnd;

    static SoundMachine * pSelf;

    pa_threaded_mainloop * pMainLoop;

    pa_context * pContext;

    pa_cvolume cVolume;

    pa_stream * pStream;

    int stream_state;

    std::function<bool( void *, size_t, size_t *) > state_write_function;

    std::function<void() > stream_drain_function;

    static void stream_write_callback(pa_stream * stream, size_t length, void * usrData);

    static void context_state_callback(pa_context * context, void * usrData);
    
    static void stream_state_callback(pa_stream * stream, void * userData);

    static void stream_drain_complete(pa_stream * stream, int success, void * usrData);
    
    static void stream_success_callback( pa_stream * stream, int success, void * usrData ){
        pa_threaded_mainloop_signal( pSelf->pMainLoop, 0 );
    }
    
    static void context_success_callback(pa_context *c, int success, void *userdata){
        pa_threaded_mainloop_signal( pSelf->pMainLoop, 0 );
    }

    SoundMachine();

    ~SoundMachine();

public:

    static SoundMachine * getSoundMachine();

    static void DelectMachine() {
        delete pSelf;
    }

    void Init();

    void CreateStream(const std::function<bool( void *, size_t, size_t *)> & write_function, const std::function<void()> & drain_function, pa_sample_format_t format = PA_SAMPLE_S16NE, int channels = 2, int rate = 44100);

    void StopStream(); //Stop the stream and pause;

    void DestroyStream();

    void Stop();

    void setVolumeDB(double db);

    void setVolumeLinear(double linear);

    void setChannelVolumeDb(int channel, double db);

    void setChannelVolumeLinear(int channel, double linear);

    void StreamPause();

    void StreamResume();

    int StreamGetState();

    unsigned long long getCurTime();

};

#endif /* SOUNDMACHINE_H_ */
